#include "Common.fx"
#include "Sampling.fx"

//--------------------------------------
struct a2v {
	a2vApplyBasic basic;
};

struct v2f {
	v2fApplyBasic basic;
};

//--------------------------------------
sampler ProjLightMapSamp : register(s2);
sampler ShadowMapSamp : register(s3);

//--------------------------------------
v2f vsMain(a2v input) {
	
	v2f output;
	
	ApplyBasicVertexProcess(output.basic, input.basic);
	
	return output;
}

//--------------------------------------
f2fb psMain(v2f input) {

	f2fb output;
	
	input.basic.lsPos.xy /= input.basic.lsPos.w;
	input.basic.lsPos.xy = saturate(input.basic.lsPos.xy);
	
	float4 lightMap = tex2D(ProjLightMapSamp, input.basic.lsPos.xy);
	
	if(input.basic.lsPos.z < 0.01)
		lightMap = 0;
	
	float2 smTexcoord;
	ShadowMapBaseTexcoord(smTexcoord, input.basic.lsPos.xy);
	
	float2 lerpWeight = frac(smTexcoord * g_ShadowMapSize);
	
	float4 smVals[4];
	float4 smResults[4];
	
	for(int i=0; i<4; ++i)
	{
		for(int j=0; j<4; ++j)
		{
			FetchOffsetedSample( smVals[i][j], ShadowMapSamp, smTexcoord, g_Uniform4x4[i * 4 + j] );
		}
		
		// compare 4 samples
		smResults[i] = input.basic.lsPos.z < smVals[i];
	}

	float shadowTerm = 0, temp;

	for(int i=0; i<3; ++i)
	{
		for(int j=0; j<3; ++j)
		{
			BilinearFilterSample(temp, smResults[i][j], smResults[i][j+1], smResults[i+1][j], smResults[i+1][j+1], lerpWeight);
			shadowTerm += temp;
		}
	}
	
	shadowTerm *= 1.0 / 9.0;
	
	lightMap *= shadowTerm;
	
	ApplyBasicFragmentProcess(output.c0, input.basic, lightMap);
	
	return output;
}

//--------------------------------------
technique Apply {

	pass {
	
		AlphaBlendEnable	= false;
		AlphaTestEnable		= false;
		
		VertexShader		= compile vs_3_0 vsMain();
		PixelShader			= compile ps_3_0 psMain();
	}
}

//--------------------------------------